
package io;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.jdom2.Element;
import org.jdom2.JDOMException;

import users.User;

/**
 * This class provides access to data for the peer review system.
 * 
 * @author Christoher M. Augg
 * @author Aaron Chen
 * 
 * @version March 19, 2014
 * 
 */
public class DataAccess extends AbstractAccess {

  // these will be removed once everything is tested outside of the data.xml file
  /** The data XML file name. */
  private static final String XML_FILE = "data.xml";

  /** A constant for the first name element in the XML file. */
  private static final String FIRSTNAME = "FirstName";

  /** A constant for the last name element in the XML file. */
  private static final String LASTNAME = "LastName";
  
  /** A constant for the UserID element in the XML file. */
  private static final String USERID = "UserID";
  
  /** A constant for the ID element in the XML file. */
  private static final String ID = "id";
  
  /** A constant for the email element in the XML file. */
  private static final String EMAIL = "email";
  
  /** A constant for the ConferenceID element in the XML file. */
  private static final String CONFID = "ConferenceID";
  
  /** A constant for the ConferenceTitle element in the XML file. */
  private static final String CONFTITLE = "ConferenceTitle";
  
  /** A constant for the RoleID element in the XML file. */
  private static final String ROLEID = "RoleID";
  
  /** A constant for the ConferenceDescription element in the XML file. */
  private static final String CONFDESCRIPTION = "ConferenceDescription";
  
  /** A constant for the ROLE element in the XML file. */
  private static final String ROLE = "Role";
  
  /**
   * A conference access object that provides connections to the database for
   * conference data.
   */
  private ConferenceAccess my_conference_access;

  /**
   * A manuscript has-a recommendation access object that provides connections
   * to the database for manuscript and recommendation related data.
   */
  private ManHasRecAccess my_man_has_rec_access;

  /**
   * A manuscript has-a review access object that provides connections to the
   * database for manuscript and review review related data.
   */
  private ManHasRevAccess my_man_has_rev_access;

  /**
   * A manuscript access object that provides connections to the database for
   * manuscript data.
   */
  private ManuscriptAccess my_manuscript_access;

  /**
   * A recommendation access object that provides connections to the database
   * for recommendation data.
   */
  private RecommendationAccess my_recommendation_access;

  /**
   * A review access object that provides connections to the database for review
   * data.
   */
  private ReviewAccess my_review_access;

  /**
   * A role access object that provides connections to the database for role
   * data.
   */
  private RoleAccess my_role_access;

  /**
   * A user access object that provides connections to the database for user
   * data.
   */
  private UserAccess my_user_access;

  /**
   * A user has-a conference has-a manuscript object that provides connections
   * to the database for user, conference, and manuscript relational data.
   */
  private UserHasConfHasManAccess my_user_has_conf_has_man_access;

  /**
   * A user has-a conference and role object that provides connections to the
   * database for user, conference, and role relational data.
   */
  private UserHasConfRoleAccess my_user_has_confrole_access;
  
  /**
   * The constructor to instantiate the DataAccess objects.
   * 
   * @throws IOException If there is a problem establishing connectivity to the
   *           file.
   * @throws JDOMException If the file cannot be correctly parsed.
   */
  public DataAccess() throws IOException, JDOMException {
    super(XML_FILE);
    createAccessObj();

  }

  /**
   * A private helper method to create access objects.
   * 
   * @throws IOException If there is a problem establishing connectivity to the
   *           file.
   * @throws JDOMException If the file cannot be correctly parsed.
   */
  private void createAccessObj() throws IOException, JDOMException {
    my_conference_access = new ConferenceAccess();
    my_man_has_rec_access = new ManHasRecAccess();
    my_man_has_rev_access = new ManHasRevAccess();
    my_manuscript_access = new ManuscriptAccess();
    my_recommendation_access = new RecommendationAccess();
    my_review_access = new ReviewAccess();
    my_role_access = new RoleAccess();
    my_user_access = new UserAccess();
    my_user_has_conf_has_man_access = new UserHasConfHasManAccess();
    my_user_has_confrole_access = new UserHasConfRoleAccess();

  }

  /**
   * Get method to access the conference database.
   * 
   * @return the conference access object.
   */
  public ConferenceAccess accessConf() {
    return my_conference_access;
  }

  /**
   * Get method to access the manuscript and recommendation relational data.
   * 
   * @return the manuscript has recommendations object.
   */
  public ManHasRecAccess accessManRec() {
    return my_man_has_rec_access;
  }

  /**
   * Get method to access the manuscript and review relational data.
   * 
   * @return the manuscript has review objects.
   */
  public ManHasRevAccess accessManRev() {
    return my_man_has_rev_access;
  }

  /**
   * Get method to access the manuscript data.
   * 
   * @return the manuscript access object.
   */
  public ManuscriptAccess accessManuscript() {
    return my_manuscript_access;
  }

  /**
   * Get method to access the recommendation data.
   * 
   * @return the recommendation access object.
   */
  public RecommendationAccess accessRec() {
    return my_recommendation_access;
  }

  /**
   * Get method to access the review data.
   * 
   * @return the review access object.
   */
  public ReviewAccess accessRev() {
    return my_review_access;
  }

  /**
   * Get method to access the role data.
   * 
   * @return the role access object.
   */
  public RoleAccess accessRole() {
    return my_role_access;
  }
  
  /**
   * Get method to access the user data.
   * 
   * @return the user access object.
   */
  public UserAccess accessUser() {
    return my_user_access;
  }
  
  /**
   * Get method to access the user has conference and manuscript data.
   * 
   * @return the UserHasConfHasManAccess access object for relational data.
   */
  public UserHasConfHasManAccess accessUserConfMan() {
    return my_user_has_conf_has_man_access;
  }
  
  /**
   * Get method to access the user has conference and role data.
   * 
   * @return the UserHasConfRoleAccess access object for relational data.
   */
  public UserHasConfRoleAccess accessUserConfRole() {
    return my_user_has_confrole_access;
  }

  /**
   * This method allows you to retrieve the data for a specific user if they are
   * in the XML file. An empty list is returned if they do not exist in the XML
   * file.
   * 
   * @param the_fname The first name to be passed in for equality checking.
   * @param the_lname The last name to be passed in for equality checking.
   * @return An array list with all of the user's information if they exist and
   *         an empty list otherwise.
   */
  public List<String> getUserData(final String the_fname, final String the_lname) {

    /** An array list to hold the user's information. */
    final List<String> userdata = new ArrayList<String>();

    final Element rootnode = getDoc().getRootElement();
    final List<Element> list = rootnode.getChildren(USERID);

    for (int i = 0; i < list.size(); i++) {

      final Element node = (Element) list.get(i);

      if (node.getChildText(FIRSTNAME).equals(the_fname)
          && node.getChildText(LASTNAME).equals(the_lname)) {

        userdata.add(node.getAttributeValue(ID));
        userdata.add(node.getChildText(FIRSTNAME));
        userdata.add(node.getChildText(LASTNAME));
        userdata.add(node.getChildText(EMAIL));
        userdata.add(node.getChildText(CONFID));
        userdata.add(node.getChildText(CONFTITLE));
        userdata.add(node.getChildText(ROLEID));
        userdata.add(node.getChildText(CONFDESCRIPTION));
        userdata.add(node.getChildText(ROLE));
      }
    }

    return userdata;
  }

  /**
   * Registers the user into the system.
   * 
   * @param the_user The User data object.
   */
  public void registerUserData(final User the_user) {

    final Element rootnode = getDoc().getRootElement();
    final Element usernode = new Element(USERID);
    rootnode.addContent(usernode);

    final long id = getNextID();
    usernode.setAttribute(ID, Long.toString(id));
    the_user.setID(id);
    usernode.addContent(new Element(ID).setText(Long.toString(the_user.getID())));
    usernode.addContent(new Element(FIRSTNAME).setText(the_user.getFirstName()));
    usernode.addContent(new Element(LASTNAME).setText(the_user.getLastName()));
    usernode.addContent(new Element(EMAIL).setText(the_user.getEmail()));
    usernode.addContent(new Element(CONFID));
    usernode.addContent(new Element(CONFTITLE));
    usernode.addContent(new Element(ROLEID));
    usernode.addContent(new Element(CONFDESCRIPTION));
    usernode.addContent(new Element(ROLE));

    writeToDatabase();

  }

}
